﻿/*    Copyright 2012 Robert Williams
    
    This file is part of FileEventWatcher.

    FileEventWatcher is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    FileEventWatcher is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with FileEventWatcher.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;

namespace FileEventWatcher
{
    public partial class Form1 : Form
    {
        static String tailProc = String.Empty;
        static Queue monitoredFiles = new Queue();
        public String ErrorLabelText = string.Empty;
        static String sDetectedAction = string.Empty;
        static bool doRunProg = false;

        // Create a new FileSystemWatcher and set its properties.
        System.IO.FileSystemWatcher watcher = new System.IO.FileSystemWatcher();

        public Form1()
        {
            InitializeComponent();
            errorLabel.Text = string.Empty; ;
            this.ShowIcon = true;
            this.ShowInTaskbar = true;
        }

        private void buttonEnd_Click(object sender, EventArgs e)
        {
            if (tailProc.Length == 0)
                cbRunProg.Checked = false;

            Application.UserAppDataRegistry.SetValue("RunFileMonitorBoxChecked", cbRunProg.Checked == true ? "true" : "false");
            this.Close();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if (Application.UserAppDataRegistry.ValueCount == 0)
                InitializeSettings();

            GetSettings();

            this.Text = String.Format("FileEventWatcher Monitoring {0}", watcher.Path.ToString());

            /* Watch for changes in LastAccess and LastWrite times, and
               the renaming of files or directories. */
            watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
               | NotifyFilters.FileName | NotifyFilters.DirectoryName;

            // Begin watching.
            if (watcher.Path != String.Empty)
                watcher.EnableRaisingEvents = true;
        }

        // Define the event handlers.
        private void OnChanged(object source, FileSystemEventArgs e)
        {
            sDetectedAction = "Changed";
            doRunProg = true;
            HandleFileSystemEvent(e);
        }

        private void OnCreated(object source, FileSystemEventArgs e)
        {
            sDetectedAction = "Created";
            doRunProg = true;
            HandleFileSystemEvent(e);
        }

        private void OnDeleted(object source, FileSystemEventArgs e)
        {
            sDetectedAction = "Deleted";
            doRunProg = false;
            HandleFileSystemEvent(e);
        }

        private void OnRenamed(object source, FileSystemEventArgs e)
        {
            sDetectedAction = "Renamed";
            doRunProg = false;
            HandleFileSystemEvent(e);
        }

        private void HandleFileSystemEvent(FileSystemEventArgs e)
        {
            bool isNewFile = true;

            if (monitoredFiles.Count > 0)
            {
                foreach (String monitoredFile in monitoredFiles)
                {
                    if (monitoredFile == e.Name)
                    {
                        isNewFile = false;
                        break;
                    }
                }
            }

            if (isNewFile == true)
            {
                monitoredFiles.Enqueue(e.Name.ToString());
                ProcessStartInfo pInfo = new ProcessStartInfo();
                String sListViewText = "[" + DateTime.Now.ToString() + "] " + e.Name.ToString() + " " + sDetectedAction;

                try
                {
                    pInfo.FileName = tailProc;
                    pInfo.Arguments = e.FullPath;
                    // Invoke the DoWork event
                    backgroundWorker1.RunWorkerAsync(sListViewText);
                    pInfo.UseShellExecute = true;

                    if (this.cbRunProg.Checked == true && doRunProg == true)
                        Process.Start(pInfo);
                }
                catch (Exception ex)
                {
                    ErrorLabelText = ex.Message.ToString();
                    // Invoke the DoWork event
                    backgroundWorker2.RunWorkerAsync(ErrorLabelText);
                }
            }
        }

        // This delegate enables asynchronous calls for setting
        // the text property on a TextBox etc control.
        delegate void SetTextCallback(string text);

        private void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.listView1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.listView1.Items.Add(text);
            }
        }

        private void SetErrorLabel(string text)
        {
            if (this.errorLabel.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetErrorLabel);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.errorLabel.Text = text;
            }
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            if (e.Argument != null)
                SetText(e.Argument.ToString());
        }

        private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
        {

        }

        private void backgroundWorker2_RunWorkerCompleted_1(object sender, RunWorkerCompletedEventArgs e)
        {
            SetErrorLabel(ErrorLabelText);
        }

        public void GetSettings()
        {
            String sVal = String.Empty;

            try
            {
                String s = Application.UserAppDataRegistry.GetValue("PathToMonitoredDirectory").ToString();

                if (Directory.Exists(s))
                    watcher.Path = s;
            }
            catch (Exception)
            {
                watcher.Path = String.Empty;
            }

            try
            {
                String s = Application.UserAppDataRegistry.GetValue("PathToFileMonitorProgram").ToString();

                if (File.Exists(s))
                    tailProc = s;
            }
            catch (Exception)
            {
                tailProc = String.Empty;
                cbRunProg.Checked = false;
            }

            try
            {
                watcher.Filter = Application.UserAppDataRegistry.GetValue("FilesToMonitor").ToString();
            }
            catch (Exception)
            {
                watcher.Filter = String.Empty;
            }

            try
            {
                sVal = Application.UserAppDataRegistry.GetValue("RunFileMonitorBoxChecked").ToString();
                cbRunProg.Checked = (sVal.ToLower().Contains("true")) ? true : false;
            }
            catch (Exception)
            {
                cbRunProg.Checked = false;
            }

            try
            {
                sVal = Application.UserAppDataRegistry.GetValue("MonitorCreatedFiles").ToString();

                if (sVal.ToLower().Contains("true"))
                    watcher.Created += new FileSystemEventHandler(OnChanged);
            }
            catch (Exception)
            {
                SetErrorLabel("Error reading one or more registry settings. Please check the Settings Menu.");
            }

            try
            {
                sVal = Application.UserAppDataRegistry.GetValue("MonitorChangedFiles").ToString();

                if (sVal.ToLower().Contains("true"))
                    watcher.Changed += new FileSystemEventHandler(OnChanged);
            }
            catch (Exception)
            {
                SetErrorLabel("Error reading one or more registry settings. Please check the Settings Menu.");
            }

            try
            {
                sVal = Application.UserAppDataRegistry.GetValue("MonitorDeletedFiles").ToString();
                if (sVal.ToLower().Contains("true"))
                    watcher.Deleted += new FileSystemEventHandler(OnChanged);
            }
            catch (Exception)
            {
                SetErrorLabel("Error reading one or more registry settings. Please check the Settings Menu.");
            }

            try
            {
                sVal = Application.UserAppDataRegistry.GetValue("MonitorRenamedFiles").ToString();
                if (sVal.ToLower().Contains("true"))
                    watcher.Renamed += new RenamedEventHandler(OnRenamed);
            }
            catch (Exception)
            {
                SetErrorLabel("Error reading one or more registry settings. Please check the Settings Menu.");
            }


            if (tailProc.Length == 0)
                cbRunProg.Checked = false;
        }

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SettingsForm sf = new SettingsForm();
            sf.ShowDialog();
            Application.Restart();
        }

        private void InitializeSettings()
        {
            try
            {
                Application.UserAppDataRegistry.SetValue("ApplicationProductVersion", Application.ProductVersion.ToString());
                Application.UserAppDataRegistry.SetValue("PathToMonitoredDirectory", String.Empty);
                Application.UserAppDataRegistry.SetValue("PathToFileMonitorProgram", String.Empty);
                Application.UserAppDataRegistry.SetValue("FilesToMonitor", "*.*");
                Application.UserAppDataRegistry.SetValue("MonitorCreatedFiles", "true");
                Application.UserAppDataRegistry.SetValue("MonitorChangedFiles", "true");
                Application.UserAppDataRegistry.SetValue("MonitorDeletedFiles", "true");
                Application.UserAppDataRegistry.SetValue("MonitorRenamedFiles", "true");
            }
            catch (Exception)
            {
                SetErrorLabel("Error creating one or more registry settings. Please check the Settings Menu.");
            }
        }
    }
}
